Import libstdc++ from GCC 3.3.3-pre 20031106.
[dragonfly.git] / contrib / libstdc++3 / include / bits / valarray_meta.h
1 // The template and inlines for the -*- C++ -*- internal _Meta class.
2
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 // Written by Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
31
32 /** @file valarray_meta.h
33  *  This is an internal header file, included by other library headers.
34  *  You should not attempt to use it directly.
35  */
36
37 #ifndef _CPP_VALARRAY_META_H
38 #define _CPP_VALARRAY_META_H 1
39
40 #pragma GCC system_header
41
42 namespace std
43 {
44   //
45   // Implementing a loosened valarray return value is tricky.
46   // First we need to meet 26.3.1/3: we should not add more than
47   // two levels of template nesting. Therefore we resort to template
48   // template to "flatten" loosened return value types.
49   // At some point we use partial specialization to remove one level
50   // template nesting due to _Expr<>
51   //
52   
53   // This class is NOT defined. It doesn't need to.
54   template<typename _Tp1, typename _Tp2> class _Constant;
55
56   // Implementations of unary functions applied to valarray<>s.
57   // I use hard-coded object functions here instead of a generic
58   // approach like pointers to function:
59   //    1) correctness: some functions take references, others values.
60   //       we can't deduce the correct type afterwards.
61   //    2) efficiency -- object functions can be easily inlined
62   //    3) be Koenig-lookup-friendly
63
64   struct __abs
65   {
66     template<typename _Tp>
67       _Tp operator()(const _Tp& __t) const { return abs(__t); }
68   };
69
70   struct __cos
71   {
72     template<typename _Tp>
73       _Tp operator()(const _Tp& __t) const { return cos(__t); }
74   };
75
76   struct __acos
77   {
78     template<typename _Tp>
79       _Tp operator()(const _Tp& __t) const { return acos(__t); }
80   };
81
82   struct __cosh
83   {
84     template<typename _Tp>
85       _Tp operator()(const _Tp& __t) const { return cosh(__t); }
86   };
87
88   struct __sin
89   {
90     template<typename _Tp>
91       _Tp operator()(const _Tp& __t) const { return sin(__t); }
92   };
93
94   struct __asin
95   {
96     template<typename _Tp>
97       _Tp operator()(const _Tp& __t) const { return asin(__t); }
98   };
99
100   struct __sinh
101   {
102     template<typename _Tp>
103       _Tp operator()(const _Tp& __t) const { return sinh(__t); }
104   };
105
106   struct __tan
107   {
108     template<typename _Tp>
109       _Tp operator()(const _Tp& __t) const { return tan(__t); }
110   };
111
112   struct __atan
113   {
114     template<typename _Tp>
115       _Tp operator()(const _Tp& __t) const { return atan(__t); }
116   };
117
118   struct __tanh
119   {
120     template<typename _Tp>
121       _Tp operator()(const _Tp& __t) const { return tanh(__t); }
122   };
123
124   struct __exp
125   {
126     template<typename _Tp>
127       _Tp operator()(const _Tp& __t) const { return exp(__t); }
128   };
129
130   struct __log
131   {
132     template<typename _Tp>
133       _Tp operator()(const _Tp& __t) const { return log(__t); }
134   };
135
136   struct __log10
137   {
138     template<typename _Tp>
139       _Tp operator()(const _Tp& __t) const { return log10(__t); }
140   };
141
142   struct __sqrt
143   {
144     template<typename _Tp>
145       _Tp operator()(const _Tp& __t) const { return sqrt(__t); }
146   };
147
148   // In the past, we used to tailor operator applications semantics
149   // to the specialization of standard function objects (i.e. plus<>, etc.)
150   // That is incorrect.  Therefore we provide our own surrogates.
151
152   struct __unary_plus
153   {
154     template<typename _Tp>
155       _Tp operator()(const _Tp& __t) const { return +__t; }
156   };
157
158   struct __negate
159   {
160     template<typename _Tp>
161       _Tp operator()(const _Tp& __t) const { return -__t; }
162   };
163
164   struct __bitwise_not
165   {
166     template<typename _Tp>
167       _Tp operator()(const _Tp& __t) const { return ~__t; }
168   };
169
170   struct __plus
171   {
172     template<typename _Tp>
173       _Tp operator()(const _Tp& __x, const _Tp& __y) const
174       { return __x + __y; }
175   };
176
177   struct __minus
178   {
179     template<typename _Tp>
180       _Tp operator()(const _Tp& __x, const _Tp& __y) const
181       { return __x - __y; }
182   };
183
184   struct __multiplies
185   {
186     template<typename _Tp>
187       _Tp operator()(const _Tp& __x, const _Tp& __y) const
188       { return __x * __y; }
189   };
190
191   struct __divides
192   {
193     template<typename _Tp>
194       _Tp operator()(const _Tp& __x, const _Tp& __y) const
195       { return __x / __y; }
196   };
197
198   struct __modulus
199   {
200     template<typename _Tp>
201       _Tp operator()(const _Tp& __x, const _Tp& __y) const
202       { return __x % __y; }
203   };
204
205   struct __bitwise_xor
206   {
207     template<typename _Tp>
208       _Tp operator()(const _Tp& __x, const _Tp& __y) const
209       { return __x ^ __y; }
210   };
211
212   struct __bitwise_and
213   {
214     template<typename _Tp>
215       _Tp operator()(const _Tp& __x, const _Tp& __y) const
216       { return __x & __y; }
217   };
218
219   struct __bitwise_or
220   {
221     template<typename _Tp>
222       _Tp operator()(const _Tp& __x, const _Tp& __y) const
223       { return __x | __y; }
224   };
225
226   struct __shift_left
227   {
228     template<typename _Tp>
229       _Tp operator()(const _Tp& __x, const _Tp& __y) const
230       { return __x << __y; }
231   };
232
233   struct __shift_right
234   {
235     template<typename _Tp>
236       _Tp operator()(const _Tp& __x, const _Tp& __y) const
237       { return __x >> __y; }
238   };
239
240   struct __logical_and
241   {
242     template<typename _Tp>
243       bool operator()(const _Tp& __x, const _Tp& __y) const
244       { return __x && __y; }
245   };
246
247   struct __logical_or
248   {
249     template<typename _Tp>
250       bool operator()(const _Tp& __x, const _Tp& __y) const
251       { return __x || __y; }
252   };
253
254   struct __logical_not
255   {
256     template<typename _Tp>
257       bool operator()(const _Tp& __x) const { return !__x; }
258   };
259
260   struct __equal_to
261   {
262     template<typename _Tp>
263       bool operator()(const _Tp& __x, const _Tp& __y) const
264       { return __x == __y; }
265   };
266
267   struct __not_equal_to
268   {
269     template<typename _Tp>
270       bool operator()(const _Tp& __x, const _Tp& __y) const
271       { return __x != __y; }
272   };
273
274   struct __less
275   {
276     template<typename _Tp>
277       bool operator()(const _Tp& __x, const _Tp& __y) const
278       { return __x < __y; }
279   };
280
281   struct __greater
282   {
283     template<typename _Tp>
284       bool operator()(const _Tp& __x, const _Tp& __y) const
285       { return __x > __y; }
286   };
287
288   struct __less_equal
289   {
290     template<typename _Tp>
291       bool operator()(const _Tp& __x, const _Tp& __y) const
292       { return __x <= __y; }
293   };
294
295   struct __greater_equal
296   {
297     template<typename _Tp>
298       bool operator()(const _Tp& __x, const _Tp& __y) const
299       { return __x >= __y; }
300   };
301
302   // The few binary functions we miss.
303   struct __atan2
304   {
305     template<typename _Tp>
306       _Tp operator()(const _Tp& __x, const _Tp& __y) const
307       { return atan2(__x, __y); }
308   };
309
310   struct __pow
311   {
312     template<typename _Tp>
313       _Tp operator()(const _Tp& __x, const _Tp& __y) const
314       { return pow(__x, __y); }
315   };
316
317
318   // We need these bits in order to recover the return type of
319   // some functions/operators now that we're no longer using
320   // function templates.
321   template<typename, typename _Tp>
322     struct __fun
323     {
324       typedef _Tp result_type;
325     };
326
327   // several specializations for relational operators.
328   template<typename _Tp>
329     struct __fun<__logical_not, _Tp>
330     {
331       typedef bool result_type;
332     };
333
334   template<typename _Tp>
335     struct __fun<__logical_and, _Tp>
336     {
337       typedef bool result_type;
338     };
339
340   template<typename _Tp>
341     struct __fun<__logical_or, _Tp>
342     {
343       typedef bool result_type;
344     };
345
346   template<typename _Tp>
347     struct __fun<__less, _Tp>
348     {
349       typedef bool result_type;
350     };
351
352   template<typename _Tp>
353     struct __fun<__greater, _Tp>
354     {
355       typedef bool result_type;
356     };
357
358   template<typename _Tp>
359     struct __fun<__less_equal, _Tp>
360     {
361       typedef bool result_type;
362     };
363
364   template<typename _Tp>
365     struct __fun<__greater_equal, _Tp>
366     {
367       typedef bool result_type;
368     };
369
370   template<typename _Tp>
371     struct __fun<__equal_to, _Tp>
372     {
373       typedef bool result_type;
374     };
375
376   template<typename _Tp>
377     struct __fun<__not_equal_to, _Tp>
378     {
379       typedef bool result_type;
380     };
381
382     //
383     // Apply function taking a value/const reference closure
384     //
385
386   template<typename _Dom, typename _Arg>
387     class _FunBase 
388     {
389     public:
390       typedef typename _Dom::value_type value_type;
391       
392       _FunBase(const _Dom& __e, value_type __f(_Arg))
393         : _M_expr(__e), _M_func(__f) {}
394
395       value_type operator[](size_t __i) const
396       { return _M_func (_M_expr[__i]); }
397
398       size_t size() const { return _M_expr.size ();}
399
400     private:
401         const _Dom& _M_expr;
402         value_type (*_M_func)(_Arg);
403     };
404
405   template<class _Dom>
406     struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type> 
407     {
408       typedef _FunBase<_Dom, typename _Dom::value_type> _Base;
409       typedef typename _Base::value_type value_type;
410       typedef value_type _Tp;
411     
412       _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {}
413     };
414
415   template<typename _Tp>
416     struct _ValFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, _Tp>
417     {
418       typedef _FunBase<valarray<_Tp>, _Tp> _Base;
419       typedef _Tp value_type;
420       
421       _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {}
422     };
423
424   template<class _Dom>
425     struct _RefFunClos<_Expr,_Dom> :
426         _FunBase<_Dom, const typename _Dom::value_type&> 
427     {
428       typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base;
429       typedef typename _Base::value_type value_type;
430       typedef value_type _Tp;
431       
432       _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&))
433         : _Base(__e, __f) {}
434     };
435
436   template<typename _Tp>
437     struct _RefFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, const _Tp&> 
438     {
439       typedef _FunBase<valarray<_Tp>, const _Tp&> _Base;
440       typedef _Tp value_type;
441       
442       _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&))
443         : _Base(__v, __f) {}
444     };
445     
446   //
447   // Unary expression closure.
448   //
449
450   template<class _Oper, class _Arg>
451     class _UnBase
452     {
453     public:
454       typedef typename _Arg::value_type _Vt;
455       typedef typename __fun<_Oper, _Vt>::result_type value_type;
456
457       _UnBase(const _Arg& __e) : _M_expr(__e) {}
458
459       value_type operator[](size_t __i) const
460       { return _Oper()(_M_expr[__i]); }
461
462       size_t size() const { return _M_expr.size(); }
463
464     private:
465       const _Arg& _M_expr;
466     };
467
468   template<class _Oper, class _Dom>
469     struct _UnClos<_Oper, _Expr, _Dom> :  _UnBase<_Oper, _Dom>
470     {
471       typedef _Dom _Arg;
472       typedef _UnBase<_Oper, _Dom> _Base;
473       typedef typename _Base::value_type value_type;
474       
475       _UnClos(const _Arg& __e) : _Base(__e) {}
476     };
477
478   template<class _Oper, typename _Tp>
479     struct _UnClos<_Oper, _ValArray, _Tp> : _UnBase<_Oper, valarray<_Tp> > 
480     {
481       typedef valarray<_Tp> _Arg;
482       typedef _UnBase<_Oper, valarray<_Tp> > _Base;
483       typedef typename _Base::value_type value_type;
484       
485       _UnClos(const _Arg& __e) : _Base(__e) {}
486     };
487
488
489   //
490   // Binary expression closure.
491   //
492
493   template<class _Oper, class _FirstArg, class _SecondArg>
494     class _BinBase 
495     {
496     public:
497         typedef typename _FirstArg::value_type _Vt;
498         typedef typename __fun<_Oper, _Vt>::result_type value_type;
499
500       _BinBase(const _FirstArg& __e1, const _SecondArg& __e2)
501         : _M_expr1(__e1), _M_expr2(__e2) {}
502       
503       value_type operator[](size_t __i) const
504       { return _Oper()(_M_expr1[__i], _M_expr2[__i]); }
505
506       size_t size() const { return _M_expr1.size(); }
507         
508     private:
509       const _FirstArg& _M_expr1;
510       const _SecondArg& _M_expr2;
511     };
512
513
514   template<class _Oper, class _Clos>
515     class _BinBase2
516     {
517     public:
518       typedef typename _Clos::value_type _Vt;
519       typedef typename __fun<_Oper, _Vt>::result_type value_type;
520
521       _BinBase2(const _Clos& __e, const _Vt& __t)
522         : _M_expr1(__e), _M_expr2(__t) {}
523
524       value_type operator[](size_t __i) const
525       { return _Oper()(_M_expr1[__i], _M_expr2); }
526
527       size_t size() const { return _M_expr1.size(); }
528
529     private:
530       const _Clos& _M_expr1;
531       const _Vt& _M_expr2;
532     };
533
534   template<class _Oper, class _Clos>
535     class _BinBase1
536     {
537     public:
538       typedef typename _Clos::value_type _Vt;
539       typedef typename __fun<_Oper, _Vt>::result_type value_type;
540
541       _BinBase1(const _Vt& __t, const _Clos& __e)
542         : _M_expr1(__t), _M_expr2(__e) {}
543
544       value_type operator[](size_t __i) const
545       { return _Oper()(_M_expr1, _M_expr2[__i]); }
546       
547       size_t size() const { return _M_expr2.size(); }
548
549     private:
550       const _Vt& _M_expr1;
551       const _Clos& _M_expr2;
552     };
553     
554   template<class _Oper, class _Dom1, class _Dom2>
555     struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2>
556         : _BinBase<_Oper,_Dom1,_Dom2> 
557     {
558       typedef _BinBase<_Oper,_Dom1,_Dom2> _Base;
559       typedef typename _Base::value_type value_type;
560         
561       _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {}
562     };
563
564   template<class _Oper, typename _Tp>
565     struct _BinClos<_Oper,_ValArray,_ValArray,_Tp,_Tp>
566       : _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > 
567     {
568       typedef _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > _Base;
569       typedef _Tp value_type;
570
571       _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w)
572         : _Base(__v, __w) {}
573     };
574
575   template<class _Oper, class _Dom>
576     struct _BinClos<_Oper,_Expr,_ValArray,_Dom,typename _Dom::value_type>
577       : _BinBase<_Oper,_Dom,valarray<typename _Dom::value_type> > 
578     {
579       typedef typename _Dom::value_type _Tp;
580       typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base;
581       typedef typename _Base::value_type value_type;
582       
583       _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2)
584         : _Base(__e1, __e2) {}
585     };
586
587   template<class _Oper, class _Dom>
588     struct  _BinClos<_Oper,_ValArray,_Expr,typename _Dom::value_type,_Dom>
589       : _BinBase<_Oper,valarray<typename _Dom::value_type>,_Dom> 
590     {
591       typedef typename _Dom::value_type _Tp;
592       typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base;
593       typedef typename _Base::value_type value_type;
594       
595       _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2)
596         : _Base(__e1, __e2) {}
597     };
598
599   template<class _Oper, class _Dom>
600     struct _BinClos<_Oper,_Expr,_Constant,_Dom,typename _Dom::value_type>
601       : _BinBase2<_Oper,_Dom> 
602     {
603       typedef typename _Dom::value_type _Tp;
604       typedef _BinBase2<_Oper,_Dom> _Base;
605       typedef typename _Base::value_type value_type;
606       
607       _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {}
608     };
609
610   template<class _Oper, class _Dom>
611     struct _BinClos<_Oper,_Constant,_Expr,typename _Dom::value_type,_Dom>
612       : _BinBase1<_Oper,_Dom> 
613     {
614       typedef typename _Dom::value_type _Tp;
615       typedef _BinBase1<_Oper,_Dom> _Base;
616       typedef typename _Base::value_type value_type;
617       
618       _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {}
619     };
620     
621   template<class _Oper, typename _Tp>
622     struct _BinClos<_Oper,_ValArray,_Constant,_Tp,_Tp>
623       : _BinBase2<_Oper,valarray<_Tp> > 
624     {
625       typedef _BinBase2<_Oper,valarray<_Tp> > _Base;
626       typedef typename _Base::value_type value_type;
627       
628       _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {}
629     };
630
631   template<class _Oper, typename _Tp>
632     struct _BinClos<_Oper,_Constant,_ValArray,_Tp,_Tp>
633       : _BinBase1<_Oper,valarray<_Tp> > 
634     {
635       typedef _BinBase1<_Oper,valarray<_Tp> > _Base;
636       typedef typename _Base::value_type value_type;
637       
638       _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {}
639     };
640         
641
642     //
643     // slice_array closure.
644     //
645     template<typename _Dom>  class _SBase {
646     public:
647         typedef typename _Dom::value_type value_type;
648
649         _SBase (const _Dom& __e, const slice& __s)
650                 : _M_expr (__e), _M_slice (__s) {}
651         value_type operator[] (size_t __i) const
652         { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; }
653         size_t size() const { return _M_slice.size (); }
654
655     private:
656         const _Dom& _M_expr;
657         const slice& _M_slice;
658     };
659
660     template<typename _Tp> class _SBase<_Array<_Tp> > {
661     public:
662         typedef _Tp value_type;
663
664         _SBase (_Array<_Tp> __a, const slice& __s)
665                 : _M_array (__a._M_data+__s.start()), _M_size (__s.size()),
666                   _M_stride (__s.stride()) {}
667         value_type operator[] (size_t __i) const
668         { return _M_array._M_data[__i * _M_stride]; }
669         size_t size() const { return _M_size; }
670
671     private:
672         const _Array<_Tp> _M_array;
673         const size_t _M_size;
674         const size_t _M_stride;
675     };
676
677     template<class _Dom> struct  _SClos<_Expr,_Dom> : _SBase<_Dom> {
678         typedef _SBase<_Dom> _Base;
679         typedef typename _Base::value_type value_type;
680         
681         _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {}
682     };
683
684     template<typename _Tp>
685     struct _SClos<_ValArray,_Tp> : _SBase<_Array<_Tp> > {
686         typedef  _SBase<_Array<_Tp> > _Base;
687         typedef _Tp value_type;
688
689         _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {}
690     };
691
692     //
693     // gslice_array closure.
694     //
695     template<class _Dom> class _GBase {
696     public:
697         typedef typename _Dom::value_type value_type;
698         
699         _GBase (const _Dom& __e, const valarray<size_t>& __i)
700                 : _M_expr (__e), _M_index(__i) {}
701         value_type operator[] (size_t __i) const
702         { return _M_expr[_M_index[__i]]; }
703         size_t size () const { return _M_index.size(); }
704         
705     private:
706         const _Dom&      _M_expr;
707         const valarray<size_t>& _M_index;
708     };
709     
710     template<typename _Tp> class _GBase<_Array<_Tp> > {
711     public:
712         typedef _Tp value_type;
713         
714         _GBase (_Array<_Tp> __a, const valarray<size_t>& __i)
715                 : _M_array (__a), _M_index(__i) {}
716         value_type operator[] (size_t __i) const
717         { return _M_array._M_data[_M_index[__i]]; }
718         size_t size () const { return _M_index.size(); }
719         
720     private:
721         const _Array<_Tp>     _M_array;
722         const valarray<size_t>& _M_index;
723     };
724
725     template<class _Dom> struct _GClos<_Expr,_Dom> : _GBase<_Dom> {
726         typedef _GBase<_Dom> _Base;
727         typedef typename _Base::value_type value_type;
728
729         _GClos (const _Dom& __e, const valarray<size_t>& __i)
730                 : _Base (__e, __i) {}
731     };
732
733     template<typename _Tp>
734     struct _GClos<_ValArray,_Tp> : _GBase<_Array<_Tp> > {
735         typedef _GBase<_Array<_Tp> > _Base;
736         typedef typename _Base::value_type value_type;
737
738         _GClos (_Array<_Tp> __a, const valarray<size_t>& __i)
739                 : _Base (__a, __i) {}
740     };
741
742     //
743     // indirect_array closure
744     //
745
746     template<class _Dom> class _IBase {
747     public:
748         typedef typename _Dom::value_type value_type;
749
750         _IBase (const _Dom& __e, const valarray<size_t>& __i)
751                 : _M_expr (__e), _M_index (__i) {}
752         value_type operator[] (size_t __i) const
753         { return _M_expr[_M_index[__i]]; }
754         size_t size() const { return _M_index.size(); }
755         
756     private:
757         const _Dom&         _M_expr;
758         const valarray<size_t>& _M_index;
759     };
760
761     template<class _Dom> struct _IClos<_Expr,_Dom> : _IBase<_Dom> {
762         typedef _IBase<_Dom> _Base;
763         typedef typename _Base::value_type value_type;
764
765         _IClos (const _Dom& __e, const valarray<size_t>& __i)
766                 : _Base (__e, __i) {}
767     };
768
769     template<typename _Tp>
770     struct _IClos<_ValArray,_Tp>  : _IBase<valarray<_Tp> > {
771         typedef _IBase<valarray<_Tp> > _Base;
772         typedef _Tp value_type;
773
774         _IClos (const valarray<_Tp>& __a, const valarray<size_t>& __i)
775                 : _Base (__a, __i) {}
776     };
777
778   //
779   // class _Expr
780   //      
781   template<class _Clos, typename _Tp> 
782     class _Expr
783     {
784     public:
785       typedef _Tp value_type;
786       
787       _Expr(const _Clos&);
788       
789       const _Clos& operator()() const;
790         
791       value_type operator[](size_t) const;
792       valarray<value_type> operator[](slice) const;
793       valarray<value_type> operator[](const gslice&) const;
794       valarray<value_type> operator[](const valarray<bool>&) const;
795       valarray<value_type> operator[](const valarray<size_t>&) const;
796     
797       _Expr<_UnClos<__unary_plus,std::_Expr,_Clos>, value_type>
798         operator+() const;
799
800       _Expr<_UnClos<__negate,std::_Expr,_Clos>, value_type>
801         operator-() const;
802
803       _Expr<_UnClos<__bitwise_not,std::_Expr,_Clos>, value_type>
804         operator~() const;
805
806       _Expr<_UnClos<__logical_not,std::_Expr,_Clos>, bool>
807         operator!() const;
808
809       size_t size() const;
810       value_type sum() const;
811         
812       valarray<value_type> shift(int) const;
813       valarray<value_type> cshift(int) const;
814
815       value_type min() const;
816       value_type max() const;
817
818       valarray<value_type> apply(value_type (*)(const value_type&)) const;
819       valarray<value_type> apply(value_type (*)(value_type)) const;
820         
821     private:
822       const _Clos _M_closure;
823     };
824     
825   template<class _Clos, typename _Tp>
826     inline
827     _Expr<_Clos,_Tp>::_Expr(const _Clos& __c) : _M_closure(__c) {}
828     
829   template<class _Clos, typename _Tp>
830     inline const _Clos&
831     _Expr<_Clos,_Tp>::operator()() const
832     { return _M_closure; }
833
834   template<class _Clos, typename _Tp>
835     inline _Tp
836     _Expr<_Clos,_Tp>::operator[](size_t __i) const
837     { return _M_closure[__i]; }
838
839   template<class _Clos, typename _Tp>
840     inline valarray<_Tp>
841     _Expr<_Clos,_Tp>::operator[](slice __s) const
842     { return _M_closure[__s]; }
843     
844   template<class _Clos, typename _Tp>
845     inline valarray<_Tp>
846     _Expr<_Clos,_Tp>::operator[](const gslice& __gs) const
847     { return _M_closure[__gs]; }
848     
849   template<class _Clos, typename _Tp>
850     inline valarray<_Tp>
851     _Expr<_Clos,_Tp>::operator[](const valarray<bool>& __m) const
852     { return _M_closure[__m]; }
853     
854   template<class _Clos, typename _Tp>
855     inline valarray<_Tp>
856     _Expr<_Clos,_Tp>::operator[](const valarray<size_t>& __i) const
857     { return _M_closure[__i]; }
858     
859   template<class _Clos, typename _Tp>
860     inline size_t
861     _Expr<_Clos,_Tp>::size() const  { return _M_closure.size (); }
862
863   template<class _Clos, typename _Tp>
864     inline valarray<_Tp>
865     _Expr<_Clos, _Tp>::shift(int __n) const
866     { return valarray<_Tp>(_M_closure).shift(__n); }
867
868   template<class _Clos, typename _Tp>
869     inline valarray<_Tp>
870     _Expr<_Clos, _Tp>::cshift(int __n) const
871     { return valarray<_Tp>(_M_closure).cshift(__n); }
872
873   template<class _Clos, typename _Tp>
874     inline valarray<_Tp>
875     _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const
876     { return valarray<_Tp>(_M_closure).apply(__f); }
877     
878   template<class _Clos, typename _Tp>
879     inline valarray<_Tp>
880     _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const
881     { return valarray<_Tp>(_M_closure).apply(__f); }
882
883   // XXX: replace this with a more robust summation algorithm.
884   template<class _Clos, typename _Tp>
885     inline _Tp
886     _Expr<_Clos,_Tp>::sum() const
887     {
888       size_t __n = _M_closure.size();
889       if (__n == 0) 
890         return _Tp();
891       else 
892         {
893           _Tp __s = _M_closure[--__n];
894           while (__n != 0)
895             __s += _M_closure[--__n];
896           return __s;
897         }
898     }
899
900   template<class _Clos, typename _Tp>
901     inline _Tp
902     _Expr<_Clos, _Tp>::min() const
903     { return __valarray_min(_M_closure); }
904
905   template<class _Clos, typename _Tp>
906     inline _Tp
907     _Expr<_Clos, _Tp>::max() const
908     { return __valarray_max(_M_closure); }
909     
910   template<class _Dom, typename _Tp>
911     inline _Expr<_UnClos<__logical_not,_Expr,_Dom>, bool>
912     _Expr<_Dom,_Tp>::operator!() const
913     {
914       typedef _UnClos<__logical_not,std::_Expr,_Dom> _Closure;
915       return _Expr<_Closure,_Tp>(_Closure(this->_M_closure));
916     }
917
918 #define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name)                           \
919   template<class _Dom, typename _Tp>                                      \
920     inline _Expr<_UnClos<_Name,std::_Expr,_Dom>,_Tp>                      \
921     _Expr<_Dom,_Tp>::operator _Op() const                                 \
922     {                                                                     \
923       typedef _UnClos<_Name,std::_Expr,_Dom> _Closure;                    \
924       return _Expr<_Closure,_Tp>(_Closure(this->_M_closure));             \
925     }
926
927     _DEFINE_EXPR_UNARY_OPERATOR(+, __unary_plus)
928     _DEFINE_EXPR_UNARY_OPERATOR(-, __negate)
929     _DEFINE_EXPR_UNARY_OPERATOR(~, __bitwise_not)
930
931 #undef _DEFINE_EXPR_UNARY_OPERATOR
932
933
934 #define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name)                        \
935   template<class _Dom1, class _Dom2>                                    \
936   inline _Expr<_BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2>,                 \
937          typename __fun<_Name, typename _Dom1::value_type>::result_type>\
938   operator _Op(const _Expr<_Dom1,typename _Dom1::value_type>& __v,      \
939                const _Expr<_Dom2,typename _Dom2::value_type>& __w)      \
940   {                                                                     \
941     typedef typename _Dom1::value_type _Arg;                            \
942     typedef typename __fun<_Name, _Arg>::result_type _Value;            \
943     typedef _BinClos<_Name,_Expr,_Expr,_Dom1,_Dom2> _Closure;           \
944     return _Expr<_Closure,_Value>(_Closure(__v(), __w()));              \
945   }                                                                     \
946                                                                         \
947 template<class _Dom>                                                    \
948 inline _Expr<_BinClos<_Name,_Expr,_Constant,_Dom,typename _Dom::value_type>,\
949              typename __fun<_Name, typename _Dom::value_type>::result_type>\
950 operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __v,          \
951              const typename _Dom::value_type& __t)                      \
952 {                                                                       \
953   typedef typename _Dom::value_type _Arg;                               \
954   typedef typename __fun<_Name, _Arg>::result_type _Value;              \
955   typedef _BinClos<_Name,_Expr,_Constant,_Dom,_Arg> _Closure;           \
956   return _Expr<_Closure,_Value>(_Closure(__v(), __t));                  \
957 }                                                                       \
958                                                                         \
959 template<class _Dom>                                                    \
960 inline _Expr<_BinClos<_Name,_Constant,_Expr,typename _Dom::value_type,_Dom>,\
961              typename __fun<_Name, typename _Dom::value_type>::result_type>\
962 operator _Op(const typename _Dom::value_type& __t,                      \
963              const _Expr<_Dom,typename _Dom::value_type>& __v)          \
964 {                                                                       \
965   typedef typename _Dom::value_type _Arg;                               \
966   typedef typename __fun<_Name, _Arg>::result_type _Value;              \
967   typedef _BinClos<_Name,_Constant,_Expr,_Arg,_Dom> _Closure;           \
968   return _Expr<_Closure,_Value>(_Closure(__t, __v()));                  \
969 }                                                                       \
970                                                                         \
971 template<class _Dom>                                                    \
972 inline _Expr<_BinClos<_Name,_Expr,_ValArray,_Dom,typename _Dom::value_type>,\
973              typename __fun<_Name, typename _Dom::value_type>::result_type>\
974 operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __e,          \
975              const valarray<typename _Dom::value_type>& __v)            \
976 {                                                                       \
977   typedef typename _Dom::value_type _Arg;                               \
978   typedef typename __fun<_Name, _Arg>::result_type _Value;              \
979   typedef _BinClos<_Name,_Expr,_ValArray,_Dom,_Arg> _Closure;           \
980   return  _Expr<_Closure,_Value>(_Closure(__e(), __v));                 \
981 }                                                                       \
982                                                                         \
983 template<class _Dom>                                                    \
984 inline _Expr<_BinClos<_Name,_ValArray,_Expr,typename _Dom::value_type,_Dom>,\
985              typename __fun<_Name, typename _Dom::value_type>::result_type>\
986 operator _Op(const valarray<typename _Dom::value_type>& __v,            \
987              const _Expr<_Dom,typename _Dom::value_type>& __e)          \
988 {                                                                       \
989   typedef typename _Dom::value_type _Tp;                                \
990   typedef typename __fun<_Name, _Tp>::result_type _Value;               \
991   typedef _BinClos<_Name,_ValArray,_Expr,_Tp,_Dom> _Closure;            \
992   return _Expr<_Closure,_Value> (_Closure (__v, __e ()));               \
993 }
994
995     _DEFINE_EXPR_BINARY_OPERATOR(+, __plus)
996     _DEFINE_EXPR_BINARY_OPERATOR(-, __minus)
997     _DEFINE_EXPR_BINARY_OPERATOR(*, __multiplies)
998     _DEFINE_EXPR_BINARY_OPERATOR(/, __divides)
999     _DEFINE_EXPR_BINARY_OPERATOR(%, __modulus)
1000     _DEFINE_EXPR_BINARY_OPERATOR(^, __bitwise_xor)
1001     _DEFINE_EXPR_BINARY_OPERATOR(&, __bitwise_and)
1002     _DEFINE_EXPR_BINARY_OPERATOR(|, __bitwise_or)
1003     _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
1004     _DEFINE_EXPR_BINARY_OPERATOR(>>, __shift_right)
1005     _DEFINE_EXPR_BINARY_OPERATOR(&&, __logical_and)
1006     _DEFINE_EXPR_BINARY_OPERATOR(||, __logical_or)
1007     _DEFINE_EXPR_BINARY_OPERATOR(==, __equal_to)
1008     _DEFINE_EXPR_BINARY_OPERATOR(!=, __not_equal_to)
1009     _DEFINE_EXPR_BINARY_OPERATOR(<, __less)
1010     _DEFINE_EXPR_BINARY_OPERATOR(>, __greater)
1011     _DEFINE_EXPR_BINARY_OPERATOR(<=, __less_equal)
1012     _DEFINE_EXPR_BINARY_OPERATOR(>=, __greater_equal)
1013
1014 #undef _DEFINE_EXPR_BINARY_OPERATOR
1015
1016 #define _DEFINE_EXPR_UNARY_FUNCTION(_Name)                               \
1017   template<class _Dom>                                                   \
1018     inline _Expr<_UnClos<__##_Name,_Expr,_Dom>,typename _Dom::value_type>\
1019     _Name(const _Expr<_Dom,typename _Dom::value_type>& __e)              \
1020     {                                                                    \
1021       typedef typename _Dom::value_type _Tp;                             \
1022       typedef _UnClos<__##_Name,_Expr,_Dom> _Closure;                    \
1023       return _Expr<_Closure,_Tp>(_Closure(__e()));                       \
1024     }                                                                    \
1025                                                                          \
1026   template<typename _Tp>                                                 \
1027     inline _Expr<_UnClos<__##_Name,_ValArray,_Tp>,_Tp>                   \
1028     _Name(const valarray<_Tp>& __v)                                      \
1029     {                                                                    \
1030       typedef _UnClos<__##_Name,_ValArray,_Tp> _Closure;                 \
1031       return _Expr<_Closure,_Tp>(_Closure(__v));                         \
1032     }
1033
1034     _DEFINE_EXPR_UNARY_FUNCTION(abs)
1035     _DEFINE_EXPR_UNARY_FUNCTION(cos)
1036     _DEFINE_EXPR_UNARY_FUNCTION(acos)
1037     _DEFINE_EXPR_UNARY_FUNCTION(cosh)    
1038     _DEFINE_EXPR_UNARY_FUNCTION(sin)
1039     _DEFINE_EXPR_UNARY_FUNCTION(asin)
1040     _DEFINE_EXPR_UNARY_FUNCTION(sinh)    
1041     _DEFINE_EXPR_UNARY_FUNCTION(tan)
1042     _DEFINE_EXPR_UNARY_FUNCTION(tanh)
1043     _DEFINE_EXPR_UNARY_FUNCTION(atan)
1044     _DEFINE_EXPR_UNARY_FUNCTION(exp)    
1045     _DEFINE_EXPR_UNARY_FUNCTION(log)
1046     _DEFINE_EXPR_UNARY_FUNCTION(log10)
1047     _DEFINE_EXPR_UNARY_FUNCTION(sqrt)
1048
1049 #undef _DEFINE_EXPR_UNARY_FUNCTION
1050
1051 #define _DEFINE_EXPR_BINARY_FUNCTION(_Fun)                             \
1052   template<class _Dom1, class _Dom2>                                   \
1053     inline _Expr<_BinClos<__##_Fun,_Expr,_Expr,_Dom1,_Dom2>,           \
1054                  typename _Dom1::value_type>                           \
1055     _Fun(const _Expr<_Dom1,typename _Dom1::value_type>& __e1,          \
1056           const _Expr<_Dom2,typename _Dom2::value_type>& __e2)         \
1057     {                                                                  \
1058       typedef typename _Dom1::value_type _Tp;                          \
1059       typedef _BinClos<__##_Fun,_Expr,_Expr,_Dom1,_Dom2> _Closure;     \
1060       return _Expr<_Closure,_Tp>(_Closure(__e1(), __e2()));            \
1061     }                                                                  \
1062                                                                        \
1063   template<class _Dom>                                                 \
1064     inline _Expr<_BinClos<__##_Fun, _Expr, _ValArray, _Dom,            \
1065                           typename _Dom::value_type>,                  \
1066                  typename _Dom::value_type>                            \
1067     _Fun(const _Expr<_Dom,typename _Dom::value_type>& __e,             \
1068          const valarray<typename _Dom::value_type>& __v)               \
1069     {                                                                  \
1070       typedef typename _Dom::value_type _Tp;                           \
1071       typedef _BinClos<__##_Fun, _Expr, _ValArray, _Dom, _Tp> _Closure;\
1072       return _Expr<_Closure,_Tp>(_Closure(__e(), __v));                \
1073     }                                                                  \
1074                                                                        \
1075   template<class _Dom>                                                 \
1076     inline _Expr<_BinClos<__##_Fun, _ValArray, _Expr,                  \
1077                           typename _Dom::value_type,_Dom>,             \
1078                  typename _Dom::value_type>                            \
1079     _Fun(const valarray<typename _Dom::valarray>& __v,                 \
1080          const _Expr<_Dom,typename _Dom::value_type>& __e)             \
1081     {                                                                  \
1082       typedef typename _Dom::value_type _Tp;                           \
1083       typedef _BinClos<__##_Fun,_ValArray,_Expr,_Tp,_Dom> _Closure;    \
1084       return _Expr<_Closure,_Tp>(_Closure(__v, __e()));                \
1085     }                                                                  \
1086                                                                        \
1087   template<class _Dom>                                                 \
1088     inline _Expr<_BinClos<__##_Fun,_Expr,_Constant,_Dom,               \
1089                           typename _Dom::value_type>,                  \
1090                  typename _Dom::value_type>                            \
1091     _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e,            \
1092          const typename _Dom::value_type& __t)                         \
1093     {                                                                  \
1094       typedef typename _Dom::value_type _Tp;                           \
1095       typedef _BinClos<__##_Fun,_Expr,_Constant,_Dom,_Tp> _Closure;    \
1096       return _Expr<_Closure,_Tp>(_Closure(__e(), __t));                \
1097     }                                                                  \
1098                                                                        \
1099   template<class _Dom>                                                 \
1100     inline _Expr<_BinClos<__##_Fun,_Constant,_Expr,                    \
1101                           typename _Dom::value_type,_Dom>,             \
1102                  typename _Dom::value_type>                            \
1103     _Fun(const typename _Dom::value_type& __t,                         \
1104          const _Expr<_Dom,typename _Dom::value_type>& __e)             \
1105     {                                                                  \
1106       typedef typename _Dom::value_type _Tp;                           \
1107       typedef _BinClos<__##_Fun, _Constant,_Expr,_Tp,_Dom> _Closure;   \
1108       return _Expr<_Closure,_Tp>(_Closure(__t, __e()));                \
1109     }                                                                  \
1110                                                                        \
1111   template<typename _Tp>                                               \
1112     inline _Expr<_BinClos<__##_Fun,_ValArray,_ValArray,_Tp,_Tp>, _Tp>  \
1113     _Fun(const valarray<_Tp>& __v, const valarray<_Tp>& __w)           \
1114     {                                                                  \
1115       typedef _BinClos<__##_Fun,_ValArray,_ValArray,_Tp,_Tp> _Closure; \
1116       return _Expr<_Closure,_Tp>(_Closure(__v, __w));                  \
1117     }                                                                  \
1118                                                                        \
1119   template<typename _Tp>                                               \
1120     inline _Expr<_BinClos<__##_Fun,_ValArray,_Constant,_Tp,_Tp>,_Tp>   \
1121     _Fun(const valarray<_Tp>& __v, const _Tp& __t)                     \
1122     {                                                                  \
1123       typedef _BinClos<__##_Fun,_ValArray,_Constant,_Tp,_Tp> _Closure; \
1124       return _Expr<_Closure,_Tp>(_Closure(__v, __t));                  \
1125     }                                                                  \
1126                                                                        \
1127   template<typename _Tp>                                               \
1128     inline _Expr<_BinClos<__##_Fun,_Constant,_ValArray,_Tp,_Tp>,_Tp>   \
1129     _Fun(const _Tp& __t, const valarray<_Tp>& __v)                     \
1130     {                                                                  \
1131       typedef _BinClos<__##_Fun,_Constant,_ValArray,_Tp,_Tp> _Closure; \
1132       return _Expr<_Closure,_Tp>(_Closure(__t, __v));                  \
1133     }
1134
1135 _DEFINE_EXPR_BINARY_FUNCTION(atan2)
1136 _DEFINE_EXPR_BINARY_FUNCTION(pow)
1137
1138 #undef _DEFINE_EXPR_BINARY_FUNCTION
1139
1140 } // std::
1141
1142
1143 #endif /* _CPP_VALARRAY_META_H */
1144
1145 // Local Variables:
1146 // mode:c++
1147 // End: